package com.diaohw.platform.framework.authorization;

import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.stp.StpLogic;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author 刁海文
 * @Remark
 * @since 2023/6/11 17:44
 */
@Order(1)
@Configuration
public class AuthorizationConfig {


    @Bean
    public StpLogic getStpLogicJwt() {
        return new StpLogicJwtForSimple();
    }


    @Bean("aloneRedisTemplate")
    public StringRedisTemplate aloneRedisTemplate(Environment environment) {
        // 获取cfg对象
        RedisProperties cfg = properties(environment);
        RedisStandaloneConfiguration redisConfig = redisStandaloneConfiguration(cfg);

        LettuceClientConfiguration clientConfig = lettuceClientConfiguration(cfg);

        LettuceConnectionFactory factory = new LettuceConnectionFactory(redisConfig, clientConfig);
        factory.afterPropertiesSet();

        // 指定相应的序列化方案

        return stringRedisTemplate(factory);
    }

    private static StringRedisTemplate stringRedisTemplate(LettuceConnectionFactory factory) {
        StringRedisSerializer keySerializer = new StringRedisSerializer();
        StringRedisSerializer valueSerializer = new StringRedisSerializer();
        // 构建RedisTemplate
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(factory);
        template.setKeySerializer(keySerializer);
        template.setHashKeySerializer(keySerializer);
        template.setValueSerializer(valueSerializer);
        template.setHashValueSerializer(valueSerializer);
        template.afterPropertiesSet();
        return template;
    }

    private RedisStandaloneConfiguration redisStandaloneConfiguration(RedisProperties cfg){
        RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
        redisConfig.setHostName(cfg.getHost());
        redisConfig.setPort(cfg.getPort());
        redisConfig.setDatabase(cfg.getDatabase());
        redisConfig.setPassword(RedisPassword.of(cfg.getPassword()));
        redisConfig.setDatabase(cfg.getDatabase());
        redisConfig.setUsername(cfg.getUsername());
        return redisConfig;
    }

    private LettuceClientConfiguration lettuceClientConfiguration(RedisProperties cfg){
        GenericObjectPoolConfig<String> poolConfig = new GenericObjectPoolConfig<>();

        RedisProperties.Lettuce lettuce = cfg.getLettuce();
        RedisProperties.Pool pool = cfg.getLettuce().getPool();
        // 连接池最大连接数
        poolConfig.setMaxTotal(pool.getMaxActive());
        // 连接池中的最大空闲连接
        poolConfig.setMaxIdle(pool.getMaxIdle());
        // 连接池中的最小空闲连接
        poolConfig.setMinIdle(pool.getMinIdle());
        // 连接池最大阻塞等待时间（使用负值表示没有限制）
        poolConfig.setMaxWait(pool.getMaxWait());
        LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
        // timeout
        if (cfg.getTimeout() != null) {
            builder.commandTimeout(cfg.getTimeout());
        }
        // shutdownTimeout
        if (lettuce.getShutdownTimeout() != null) {
            builder.shutdownTimeout(lettuce.getShutdownTimeout());
        }
        // 创建Factory对象
        return builder.poolConfig(poolConfig).build();
    }


    private RedisProperties properties(Environment environment) {
        return Binder.get(environment).bind("sa-token.alone-redis", RedisProperties.class).get();
    }

}
